package cn.test.futrue.CompletableFuture;


import cn.test.entity.User;
import cn.test.service.impl.UserServiceImpl;
import org.springframework.util.StopWatch;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

//并行异步示例：CompletableFuture.supplyAsync 普通实现
public class CompletableFuture2 {

    public static void main(String[] args) {
//        testCompletable1();

        testCompletable2();
    }

    private static void testCompletable2() {
        long start = System.currentTimeMillis();
        // 结果集
        List<String> list = new ArrayList<>();

        ExecutorService executorService = Executors.newFixedThreadPool(10);

        List<Integer> taskList = Arrays.asList(2, 1, 3, 4, 5, 6, 7, 8, 9, 10);
        // 全流式处理转换成CompletableFuture[]+组装成一个无返回值CompletableFuture，join等待执行完毕。返回结果whenComplete获取
        CompletableFuture[] cf_array = taskList.stream()
                .map(
                        item1 -> CompletableFuture.supplyAsync(() -> sleepSimulate(item1), executorService)
                                .thenApply(item2 -> Integer.toString(item2))
                                .whenComplete((s, e) -> { // 封装后无返回值，必须自己whenComplete()获取
                                    System.out.println("任务" + s + "完成!result=" + s + "，异常 e=" + e + "," + new Date());
                                    list.add(s);
                                })
                ).toArray(CompletableFuture[]::new);

        CompletableFuture.allOf(cf_array).join();
        System.out.println("list=" + list + ",耗时=" + (System.currentTimeMillis() - start));
    }

    public static int sleepSimulate(Integer item) {
        try {
            if (item == 1) {
                Thread.sleep(3000);//任务1耗时3秒
            } else if (item == 5) {
                Thread.sleep(5000);//任务5耗时5秒
            } else {
                Thread.sleep(1000);//其它任务耗时1秒
            }
            System.out.println("task线程：" + Thread.currentThread().getName()
                    + "任务item=" + item + ",完成！+" + new Date());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return item;
    }

    private static void testCompletable1() {
        Executor executor = Executors.newFixedThreadPool(100);
        StopWatch stopWatch = new StopWatch();//用于准确地测量运行时间
        stopWatch.start();
        List<Long> ids = new ArrayList<>();
        ids.add(1L);
        ids.add(2L);
        ids.add(3L);
        ids.add(4L);
        List<CompletableFuture<User>> userInfoList = ids.stream().map((s) -> {
            return CompletableFuture.supplyAsync(() -> {
                UserServiceImpl userService = new UserServiceImpl();
                return userService.selectById(s);
            }, executor);
        }).collect(Collectors.toList());
        //allOf是等待所有任务完成；  anyOf是只要有一个任务完成，构造后CompletableFuture就完成
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(userInfoList.toArray(new CompletableFuture[userInfoList.size()]));

        CompletableFuture<List<User>> allFutureList = allFutures.thenApply(v -> {
            return userInfoList.stream().map(a -> {
                try {
                    //return a.get(10,TimeUnit.MILLISECONDS);
                    return a.join();
                } catch (Exception e) {
                }
                return null;
            }).collect(Collectors.toList());
        });
        List<User> list = allFutureList.join();
        for (User u : list) {
            System.out.println(u.getUsername() + "--" + u.getId());
        }
        stopWatch.stop();
        long t = stopWatch.getTotalTimeMillis();
        System.out.println(t);
    }
}
